/* eslint-disable no-new */
/* eslint-disable new-cap */
/**
 * vue手势指令
 * @param {*} element       // 指令绑定dom
 * @param {object} binding     // 指令传递方法
 * @param {string} type     // 指令类型
 */
function vueTouch(element, binding, type) {
  this.element = element
  this.binding = binding
  this.touchType = type
  this.starDis = { // 手指按下位置
    x: null,
    y: null
  }
  this.moveDis = { // 手指离开位置
    x: null,
    y: null
  }
  this.longTouch = false // 按下 （默认未按下）
  this.start = this.start.bind(this)
  this.move = this.move.bind(this)
  this.end = this.end.bind(this)
  // 定义指令回调函数
  this.vueCallBack = typeof binding.value === 'object' ? binding.value.fn : binding.value
  this.element.addEventListener('touchstart', this.start, false)
  this.element.addEventListener('touchmove', this.move, false)
  this.element.addEventListener('touchend', this.end, false)
}
vueTouch.prototype = {
  setVueCallBack(type, evt) {
    if (this.touchType === type) {
      this.vueCallBack(this.binding.value)
    }
  },
  start: function(evt) {
    this.longTouch = true
    // 赋值鼠标位置
    this.starDis = {
      x: evt.changedTouches[0].pageX,
      y: evt.changedTouches[0].pageY
    }
    // 设置定时器来模拟长按事件
    this.time = setTimeout(() => {
      if (this.longTouch) {
        this.setVueCallBack('longtap')
        this.longTouch = false
      }
    }, 1000)
  },
  move: function(evt) {
    this.moveDis = {
      x: evt.changedTouches[0].pageX,
      y: evt.changedTouches[0].pageY
    }
    evt.starDis = this.starDis
    evt.moveDis = this.moveDis
    // 滑动事件抛出坐标差
    this.setVueCallBack('swiper')
  },
  end: function(evt) {
    // 计算滑动距离 = 鼠标结束时坐标 - 鼠标点击时坐标
    let disX = evt.changedTouches[0].pageX - this.starDis.x
    let disY = evt.changedTouches[0].pageY - this.starDis.y
    // 离开的时候清除长按定时器
    clearTimeout(this.time)
    // 如果横向滑动的距离大于纵向滑动的按照左右滑动算
    if (Math.abs(disX) > Math.abs(disY)) {
      if (disX > 10) {
        this.setVueCallBack('swiperight')
      } else if (disX < -10) {
        this.setVueCallBack('swipeleft')
      }
    } else {
      if (disY > 10) {
        this.setVueCallBack('swipedown')
      } else if (disY < -10) {
        this.setVueCallBack('swipeup')
      }
    }
  }
}
// 注册自定义指令
const Touch = {}
const touchTypes = ['swipeleft', 'swiperight', 'swipedown', 'swipeup', 'longtap', 'swiper']
Touch.install = (Vue, optinons) => {
  touchTypes.forEach(key => {
    Vue.directive(key, {
      inserted: function(ele, binding) {
        new vueTouch(ele, binding, key)
      }
    })
  })
}

export default Touch
